package com.bpm.example.event.time;

import com.bpm.common.util.FlowableEngineUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.Test;

/**
 * 定时边界事件
 * 当某个用户任务或者子流程在规定的时间后还没有执行。那么我们就可以通过定时器边界事件来触发执行特定的处理流程。
 * @author curleyg
 * @version 1.0
 * @date 2020/8/31 16:06
 */
@Slf4j
public class RunTimerBoundaryEventProcessDemo extends FlowableEngineUtil {

    /**
     * 超时
     * @throws Exception
     */
    @Test
    public void runRunTimerBoundaryEventProcessDemo() throws Exception {
        //加载Flowable配置文件并初始化流程引擎及服务
        initFlowableEngineAndServices("flowable.job.xml");
        //部署流程
        ProcessDefinition procDef = deployResource("processes/TimerBoundaryEventProcess.bpmn20.xml");
        //启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId());

        //完成客户投诉
        TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstance.getId());
        Task task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

        //一线客服暂停10s
        log.info("延时20s完成");
        Thread.sleep(20*1000);

        //任务到二线客服处理
        task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

        //结案
        task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

        //获取执行时长以秒为单位
        long durationInSeconds = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstance.getId()).singleResult().getDurationInMillis()/1000;
        log.info("执行时长为:{}s",durationInSeconds);


    }

    /**
     * 不超时
     * @throws Exception
     */
    @Test
    public void runRunTimerBoundaryEventProcessDemo2() throws Exception {
        //加载Flowable配置文件并初始化流程引擎及服务
        initFlowableEngineAndServices("flowable.job.xml");
        //部署流程
        ProcessDefinition procDef = deployResource("processes/TimerBoundaryEventProcess.bpmn20.xml");
        //启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId());

        //完成客户投诉
        TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstance.getId());
        Task task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

        //一线客服不延时
        task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

        //结案
        task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

        //获取执行时长以秒为单位
        long durationInSeconds = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstance.getId()).singleResult().getDurationInMillis()/1000;
        log.info("执行时长为:{}s",durationInSeconds);


    }

    /**
     * 注意在定时器边界事件配置了cancelActivity属性，用于说明该事件是否为中断事件。
     *
     * cancelActivity属性值默认为true，表示它是边界中断事件，当该边界事件触发时，
     * 它所依附的活动实例被终止，原有的执行流会被中断，流程将沿边界事件的外出顺序流继续流转。
     *
     * 如果将其设置为false，表示它是边界非中断事件，当边界事件触发时，则原来的执行流仍然存在，
     * 所依附的活动实例继续执行，同时也执行边界事件的外出顺序流
     */
    @Test
    public void timerBoundaryEventProcessCancelActivity() throws Exception {
        //加载Flowable配置文件并初始化流程引擎及服务
        initFlowableEngineAndServices("flowable.job.xml");
        //部署流程
        ProcessDefinition procDef = deployResource("processes/TimerBoundaryEventProcessCancelActivity.bpmn20.xml");
        //启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId());
        //合同审批暂停20s
        log.info("延时20s完成");
        Thread.sleep(20*1000);

        //完成合同审批
        TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstance.getId());
        Task task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

         //财务审核暂停20s,中断了财务审核流转到实习生审批
        log.info("延时20s完成");
        Thread.sleep(20*1000);

        //完成实习生审批
        task = taskQuery.singleResult();
        log.info("当前流程到达的用户任务名称为:{}",task.getName());
        taskService.complete(task.getId());

        //获取执行时长以秒为单位
        long durationInSeconds = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstance.getId()).singleResult().getDurationInMillis()/1000;
        log.info("执行时长为:{}s",durationInSeconds);


    }

}
